/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package symulatorwindy.animation;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import symulatorwindy.SymulatorWindyView;
import symulatorwindy.logic.Pasazer;
import symulatorwindy.logic.Pietro;

/**
 *
 * @author Przemo
 */
public class Elevator implements Runnable {
    public static final int UP = 0;
    public static final int DOWN = 1;

    private ElevatorAnimation ea;
    private int floor_count;
    private final int floor_size = ElevatorAnimation.FLOOR_SIZE;
    private int time_for_floor; // Tymczasowo /* Miliseconds */
    private int actual_floor;
    private double jump_time;
    private double speed;
    private int enter_exit_time;
    private ArrayList<Pietro> trasa;
    private int elevator;
    private int direction;

    private String id;

    public Elevator(ElevatorAnimation ea, int floor_count, int elevator) {
        this.setElevatorAnimation(ea);
        this.floor_count = floor_count;
        this.elevator = elevator;
        this.speed = 1;
        this.init();
        id = "Winda "+elevator+": ";
    }

    @Override
    public void run() {
        SymulatorWindyView.LOG.info( id+"start");
        try {
            int size = trasa.size();
            for (int i = 0; i <size; i++) {
                if(i+1 < size){
                    if (trasa.get(i).numerPietra < trasa.get(i+1).numerPietra) {
                        direction = UP;
                     } else if (trasa.get(i).numerPietra > trasa.get(i+1).numerPietra) {
                        direction = DOWN;
                     }
                }
                goToFloor(trasa.get(i));
            }
            SymulatorWindyView.LOG.info("------------WINDA "+elevator+" KONIEC--------------");
        } catch (InterruptedException e) {
        }
    }

    private void init() {
        this.time_for_floor = 1000;
        this.actual_floor = 0;
        this.jump_time = ((double) this.time_for_floor) / ((double) (this.floor_size));
    }

    public void setElevatorAnimation(ElevatorAnimation ea) {
        this.ea = ea;
    }

    public void goToFloor(Pietro pietro) throws InterruptedException {
        SymulatorWindyView.LOG.info(id+ "jedzie na piętro " + pietro.numerPietra);
        if (actual_floor < pietro.numerPietra) {
            goUp(pietro.numerPietra);
        } else if (actual_floor > pietro.numerPietra) {
            goDown(pietro.numerPietra);
        }
        actual_floor = pietro.numerPietra;
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
        exitElevator(pietro.pasazerowieWysiadajacy, pietro.numerPietra);
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
        enterElevator(pietro.pasazerowieWsiadający, pietro.numerPietra);
    }

    private void goUp(int number) throws InterruptedException {
        if (this.elevator == 1) {
            while (this.ea.shift > (this.floor_size * (this.floor_count - (number + 1)))) {

                this.ea.shift--;
                this.ea.repaint();
                Thread.sleep((long) (this.jump_time * this.speed));
            }
        } else {
            while (this.ea.shift2 > (this.floor_size * (this.floor_count - (number + 1)))) {
                this.ea.shift2--;
                this.ea.repaint();
                Thread.sleep((long) (this.jump_time * this.speed));
            }
        }

    }

    private void goDown(int number) throws InterruptedException {
        if (elevator == 1) {
            while (this.ea.shift < (this.floor_size * (this.floor_count - (number + 1)))) {
                this.ea.shift++;
                this.ea.repaint();
                Thread.sleep((long) (this.jump_time * this.speed));
            }
        } else {
            while (this.ea.shift2 < (this.floor_size * (this.floor_count - (number + 1)))) {
                this.ea.shift2++;
                this.ea.repaint();
                Thread.sleep((long) (this.jump_time * this.speed));
            }
        }

    }

    private void exitElevator(List<Pasazer> ludzie, int floor) throws InterruptedException {
        if (ludzie.size() <= 0) {
            return;
        }
        SymulatorWindyView.LOG.info(id+"Wysiada " + ludzie.size() + " osób na pietrze "+floor);
        
        for (int i = 0; i < ludzie.size(); i++) {
            if (this.elevator == 1) {
                this.ea.elevator_passangers--;
                this.ea.exited_floor_passangers[floor]++;
            } else {
                this.ea.second_elevator_passangers--;
                this.ea.second_exited_floor_passangers[floor]++;
            }
            this.ea.repaint();
            Thread.sleep((long) (this.enter_exit_time * this.speed));

        }
        SymulatorWindyView.LOG.info(id+"W windzie jest " + this.ea.elevator_passangers +" osób");
    }

    private void enterElevator(List<Pasazer> ludzie, int floor) throws InterruptedException {
        if (ludzie.size() <= 0) {
            return;
        }
        SymulatorWindyView.LOG.info(id+"Wsiada "+ludzie.size()+" osób na pietrze "+floor);

        for (int i = 0; i < ludzie.size(); i++) {
            if (elevator == 1) {
                ea.elevator_passangers++;
            } else {
                ea.second_elevator_passangers++;
            }
            if(direction==UP )
                ea.floor_passengers_up[floor]--;
            else
                ea.floor_passengers_down[floor]--;
            this.ea.repaint();
            Thread.sleep((long) (this.enter_exit_time * this.speed));
        }
        SymulatorWindyView.LOG.info(id+"W windzie jest " + this.ea.elevator_passangers +" osób");
    }

    public void setTimeForFloor(int time) {
        this.time_for_floor = time;
        this.jump_time = ((double) time) / ((double) (this.floor_size));
    }

    public void setFloorsCount(int floors) {
        this.floor_count = floors;
        this.init();
    }

    public void setEnterExitTime(int time) {
        this.enter_exit_time = time;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public void setPietro(ArrayList<Pietro> pietro) {
        this.trasa = pietro;
    }
}
